package com.ctsi.commons.util.id;

import java.security.NoSuchAlgorithmException;
import java.security.NoSuchProviderException;
import java.security.SecureRandom;
import java.util.Random;
import java.util.Set;
import java.util.concurrent.ConcurrentSkipListSet;

/**
 * 线程不安全,但是如果构造后,立即执行一次,并且不修改属性,就是安全的
 * 
 * @author zhangjw
 * 
 */
public class RandomNum {

	private boolean floatvalue = false;

	private long upper = 100;

	private long lower = 0;

	private String algorithm = null;

	private String provider = null;

	private boolean secure = false;

	private Random random = null;
	private Random random2 = null;

	private Set<Number> rset = null;

	public Set<Number> getRset() {
		return rset;
	}

	public void setRset(boolean check) {
		if (check)
			this.rset = new ConcurrentSkipListSet<Number>();
	}

	private final float getFloat() {

		if (secure) {
			return random.nextFloat();
		}
		count++;
		if ((count & 1) == 0) {
			return random2.nextFloat();
		} else {
			return random.nextFloat();
		}
	}

	private int count;

	private final void generateRandomObject() {

		if (random == null) {
			if (secure) {
				try {
					// get an instance of a SecureRandom object
					if (provider != null)
						// search for algorithm in package provider
						random = SecureRandom.getInstance(algorithm, provider);
					else
						random = SecureRandom.getInstance(algorithm);
					random2 = random;
				} catch (NoSuchAlgorithmException ne) {
					throw new RuntimeException(ne.getMessage());
				} catch (NoSuchProviderException pe) {
					throw new RuntimeException(pe.getMessage());
				}
			} else {
				// 这样jdk14就没有问题了

				random = new Random();

				random2 = new MTRandom();

			}
		}

	}

	/**
	 * generate the random number
	 * 
	 */
	private final Number generaterandom() {

		if (floatvalue)
			return new Float(getFloat());
		else
			return new Long(lower + (long) ((getFloat() * (upper - lower))));
	}

	private final Number getRandomNumber() {
		generateRandomObject();
		return generaterandom();

	}

	public final Number getRandom() {

		Number result = getRandomNumber();
	 
		if (rset != null) {

			while (rset.contains(result)) {

				result = getRandomNumber();
			}

			rset.add(result);
		}

		return result;
	}

	public final void setRange(long low, long up) {

		// set the upper and lower bound of the range
		lower = low;
		upper = up;

		// check to see if a float value is expected
		if ((lower == 0) && (upper == 1))
			floatvalue = true;
	}

	/**
	 * 设置安全随机数算法
	 * 
	 * @param value
	 *            算法名称
	 * 
	 */
	public final void setAlgorithm(String value) {
		algorithm = value;
		secure = true; // a SecureRandom object is to be used
	}

	public final void setProvider(String value) {
		provider = value;
	}

	public final void setRange(String value) throws Exception {
		try {
			upper = new Long(value.substring(value.indexOf('-') + 1)).longValue();
		} catch (Exception ex) {
			throw new Exception("upper attribute could not be" + " turned into an Integer default value was used");
		}

		try {
			lower = new Long(value.substring(0, value.indexOf('-'))).longValue();
		} catch (Exception ex) {
			throw new Exception("lower attribute could not be" + " turned into an Integer default value was used");
		}

		if ((lower == 0) && (upper == 1))
			floatvalue = true;

		if (upper < lower)
			throw new Exception("You can't have a range where the lowerbound" + " is higher than the upperbound.");

	}
}
